#include "dealerComb.h"


Hand::Hand()
{
	initializeComposition();
}

Hand::Hand(const Hand &copyOf)
{
	initializeComposition();
	
	for(std::vector<int>::const_iterator i = copyOf.cards.begin();
	    i != copyOf.cards.end();
	    i++)
	{
		addCard(*i);
	}
}

void Hand::initializeComposition()
{
	for(int i = 0; i < 10; i++)
		composition[i] = 0;
}

void Hand::addCard(int value)
{
	// you could add an assertion here that value was in the range [1, 10]
	cards.push_back(value);
	composition[value % 10]++;
}

void Hand::removeLastCard()
{
	composition[cards.back() % 10]--;
	cards.pop_back();
}

void Hand::clear()
{
	cards.clear();
	initializeComposition();
}

int Hand::total()
{
	int ret = 0;
	for(int value = 1; value <= 10; value++)
		ret += value * composition[value % 10];
	
	if(ret <= 11 && composition[1] > 0)
		ret += 10;
	
	return ret;
}

void Hand::print(std::ostream &out)
{
	for(std::vector<int>::iterator i = cards.begin(); i != cards.end(); i++)
		out << "," << *i;
	out << "   total = " << total() << std::endl;
}

DealerCombinations::DealerCombinations(std::vector<int> &startingCards)
{
	current = new Hand;
	for(std::vector<int>::iterator i = startingCards.begin(); i != startingCards.end(); i++)
		current->addCard(*i);
	numStarting = startingCards.size();
	
	while(current->total() < 17)
		current->addCard(1);
}

Hand *DealerCombinations::next()
{
	if(current == NULL)
		return NULL;
	
	Hand *ret = current;
	
	current = new Hand(*ret);
	
	// we iterate through to the last card and increment it, if it can be incremented.
	// if it can't be incremented, we remove it and increment the previous card, then
	//   take hits (of aces) as necessary.
	// we do this until we're out of cards to increment.
	for(int i = current->cards.size() - 1; i >= numStarting; i--)
	{
		int lastCard = current->cards[i];
		if(current->cards[i] == 10)
		{
			current->removeLastCard();
			continue;
		}
		
		current->removeLastCard();
		current->addCard(lastCard + 1);
		if(current->total() >= 17)
			return ret;
		
		while(current->total() < 17)
			current->addCard(1);
		return ret;
	}
	
	// if we get here and we're at a valid total, it's because we started
	// with a valid total, so return it.  it'll be the only combination this
	// function ever returns.
	if(current->total() >= 17)
	{
		current = NULL;
		return ret;
	}
	
	// if we get here and have only our starting cards, we've exhausted everything
	if(current->cards.size() == numStarting)
	{
		current = NULL;
		return ret;
	}
	
	current = NULL;
	return NULL;
}